| 熱點 | 成本來源 | 因應策略 | 
|---|---|---|
| Task 分配 | GC 壓力 | 使用 ValueTask或重用 IValueTaskSource 來源 | 
| 過多 context 捕捉 | ExecutionContext 複製 | 採用 UnsafeOnCompleted 內部機制或適度使用 SuppressFlow | 
| 不必要呼叫 Task.Run | 額外排程開銷 | I/O 綁定操作直接採用原生非同步 API | 
| 延續串過長 | 多次排程與堆疊消耗 | 採用扁平化設計,避免 return await 包裹純傳遞操作 | 
| 阻塞呼叫(Result / Wait) | 線程集區耗盡 | 全鏈路改用非同步模式,必要時以 ValueTask.GetAwaiter().GetResult() 取代需確認已完成 | 
微優化檢查清單:
| 反例 | 問題 | 修正方式 | 
|---|---|---|
| 公開 API 回傳 ValueTask 但呼叫次數少 | 複雜度高於節省的配置成本 | 改回傳回 Task | 
| 多次等待同一 ValueTask | 行為未定義或觸發例外 | 先轉換為 AsTask() 再進行多次等待 | 
| lock 區塊內使用 await | 可能導致死鎖 | 改用非同步同步原語如 SemaphoreSlim | 
| 使用 async void | 例外無法攔截處理 | 僅限事件處理器使用 | 
| Result 卡住 UI 或舊版 ASP.NET | 同步等待引發死鎖 | 全鏈路非同步化並搭配 ConfigureAwait(false) | 
| 大量 Task.Run 包裹 I/O 操作 | 線程集區資源佔用 | 直接採用原生非同步 API | 
using System;
using System.Threading;
using System.Threading.Tasks;
static async Task Demo()
{
    Console.WriteLine($"A 執行緒={Environment.CurrentManagedThreadId}");
    await Task.Delay(10); // 預設捕捉 SynchronizationContext(若存在)
    Console.WriteLine($"B 執行緒={Environment.CurrentManagedThreadId}");
    await Task.Delay(10).ConfigureAwait(false); // 不捕捉 SynchronizationContext
    Console.WriteLine($"C 執行緒={Environment.CurrentManagedThreadId}");
}
await Demo();
無 UI SynchronizationContext Console 或 ASP.NET Core中,A/B/C 執行緒可能分散於線程集區或相同執行緒;WPF 環境下,B 會回傳至 UI 執行緒,C 則可能由線程集區執行。